﻿using System;
using System.Globalization;
using System.Linq;
using System.Management;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Text.RegularExpressions;

namespace DeSleeper.Library
{
    public static class WakeOnLanHelper
    {
        private const int _macSize = 6;
        private const int _recordSize = 6;
        private const int _macRepititionCount = 16;

        public static void WakeUp(string mac)
        {
            WakeUp(Mac2Byte(mac));
        }

        public static void WakeUp(PhysicalAddress mac)
        {
            WakeUp(mac.GetAddressBytes());
        }

        public static void WakeUp(byte[] mac)
        {
            using (var socket = new Socket(AddressFamily.InterNetwork,
                                           SocketType.Dgram, ProtocolType.Udp))
            {
                var endPoint = new IPEndPoint(IPAddress.Broadcast, 40000);

                socket.Connect(endPoint);

                var packet = new byte[17*_recordSize];
                for (int i = 0; i < _recordSize; i++)
                    packet[i] = 0xFF;

                for (int i = 1; i <= _macRepititionCount; i++)
                    Array.Copy(mac, 0, packet, i * _macSize, _macSize);

                socket.Send(packet);
            }
        }

        public static bool ValidateMacAddress(string macAddress)
        {
            //remove all non 0-9, A-F, a-f characters
            var filteredAddress = Regex.Replace(macAddress, @"[^0-9A-Fa-f]", "");
            //check if it is now a valid mac adress
            return filteredAddress.Length == _macSize*2;
        }

        private static byte[] Mac2Byte(string macAddress)
        {
            //remove all non 0-9, A-F, a-f characters
            var filteredAddress = Regex.Replace(macAddress, @"[^0-9A-Fa-f]", "");
            //check if it is now a valid mac adress
            if (!ValidateMacAddress(macAddress))
                throw new ArgumentException("Mac Adress must be " + (_macSize * 2) +
                                            " digits of 0-9, A-F, a-f characters in length.");

            var macBytes = new byte[_macSize];
            for (int i = 0; i < macBytes.Length; i++)
            {
                macBytes[i] = byte.Parse(filteredAddress.Substring(i * 2, 2), NumberStyles.HexNumber);
            }
            return macBytes;
        }
    }
}